package com.yin.controller;

import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.yin.entity.TokenInfoEntity;
import com.yin.entity.TokenResult;
import com.yin.entity.UserInfoEntity;
import com.yin.jpa.TokenJPA;
import com.yin.jpa.UserInfoJPA;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

/**
*@author LSY
*Time: 2018年12月27日下午3:50:59
*
*
*/
@RestController
@RequestMapping("/jwt")
public class TokenController {

	@Autowired
	private UserInfoJPA userJPA;
	
	@Autowired
	private TokenJPA tokenJPA;

	@RequestMapping(value = "/token", method = {RequestMethod.GET, RequestMethod.POST})
	public TokenResult token(@RequestParam String appId, @RequestParam String appSecret) {
		TokenResult token = new TokenResult();
		if(appId == null || appId.trim().equals("")) {
			token.setFlag(false);
			token.setMsg("appid is not found!");
		}else if(appSecret == null || appSecret.trim().equals("")) {
			token.setFlag(false);
			token.setMsg("appSecret is not found!");
		}else {
			Optional<UserInfoEntity> op = userJPA.findOne(new Specification<UserInfoEntity>() {
				/**
				 * 
				 */
				private static final long serialVersionUID = 1L;

				@Override
				public Predicate toPredicate(Root<UserInfoEntity> root, CriteriaQuery<?> query,
						CriteriaBuilder criteriaBuilder) {
					query.where(criteriaBuilder.equal(root.get("appId"), appId));
					return null;
				}
			});
			
			UserInfoEntity userInfoEntity = null;
			if(!op.isPresent()) {
				token.setFlag(false);
				token.setMsg("appId:" + appId + ",is not found!");
			}else {
				userInfoEntity = op.get();
				if(!new String(userInfoEntity.getAppSecret()).equals(appSecret.replaceAll(" ", "+"))) {
					token.setFlag(false);
					token.setMsg("appSercet is not effective");
				}else {
					Optional<TokenInfoEntity> opToken = tokenJPA.findOne(new Specification<TokenInfoEntity>() {
						/**
						 * 
						 */
						private static final long serialVersionUID = 1L;

						@Override
						public Predicate toPredicate(Root<TokenInfoEntity> root, CriteriaQuery<?> query,
								CriteriaBuilder criteriaBuilder) {
							query.where(criteriaBuilder.equal(root.get("appId"), appId));
							return null;
						}
					});
					String tokenStr = "";
					TokenInfoEntity tokenInfoEntity = null;
					if(!opToken.isPresent()) {
						tokenStr = createNewToken(appId);
						tokenInfoEntity = new TokenInfoEntity();
						tokenInfoEntity.setAppId(appId);
						tokenInfoEntity.setBuildTime(String.valueOf(System.currentTimeMillis()));
						tokenInfoEntity.setToken(tokenStr.getBytes());
						tokenJPA.save(tokenInfoEntity);
					}else {
						tokenInfoEntity = opToken.get();
						long dbBuildTime = Long.valueOf(tokenInfoEntity.getBuildTime());
						long currentTime = System.currentTimeMillis();
						long second = TimeUnit.MILLISECONDS.toSeconds(currentTime - dbBuildTime);
						if(second > 0 && second < 7200) {
							tokenStr = new String(tokenInfoEntity.getToken());
						}else {
							tokenStr = createNewToken(appId);
							tokenInfoEntity.setToken(tokenStr.getBytes());
							tokenInfoEntity.setBuildTime(String.valueOf(System.currentTimeMillis()));
							tokenJPA.save(tokenInfoEntity);
						}
					}
					token.setToken(tokenStr);
				}
			}
		}
		return token;
	}
	
	private String createNewToken(String appId) {
		Date now = new Date(System.currentTimeMillis());
		Date expiration = new Date(now.getTime() + 7200000);
		return Jwts.builder()
				.setSubject(appId)
				.setIssuedAt(now)
				.setIssuer("OnLine Builder")
				.setExpiration(expiration)
				.signWith(SignatureAlgorithm.HS256, "LSYv1.0.0")
				.compact();
	}
}
